from math import *
import os
import sys
import time

def evaluate( cases, metaheuristic, i, outputfile, test_cases):
    
    def criteria(f, nombre, global_results, global_times, global_iterations,
                 criterio, cases):
        
        f.write("\\textbf{" + nombre + "}")
        for i in range(len(cases)):
            f.write(  " & " + str(round(float(criterio(global_results[i])),4))\
                    + " & " + str(round(float(criterio(global_times[i])),4))\
                    + " & " + str(round(float(criterio(global_iterations[i])),4))
                    )
        f.write("\\\\\n\\hline\n")
    
    f = open(outputfile,"w")
    
    # Declaracion de las tablas
    f.write("\\begin{tabular}{|c|"),
    for _ in cases:
        f.write("r|r|r|"),
    
    f.write("}\n\\hline\n")
    
    #Encabezado de las tablas
    for (case, _) in cases:
        f.write("& " + case + " & T(seg) & \\#It.")
    
    print metaheuristic, cases
    
    global_results = []
    global_iterations = []
    global_times = []
    
    for (case, centroids) in cases:
        results    = [0]*test_cases
        iterations = [0]*test_cases
        times      = [0.0]*test_cases
        
        call_sys = "bin/clustrophobia -f test/" + case + ".data" +\
                    " -n " + str(centroids) +\
                    " -h " + metaheuristic +\
                    " -i " + str(i)+\
                    " -o salida.tmp > salida2.tmp; rm salida2.tmp"
        
        print "Case:", case
        
        for test in range(test_cases):
            start = time.time()
            time.sleep(0.5)
            os.system(call_sys)
            elapsed = (time.time() - start)
            
            foutput = open("salida.tmp")
            output = foutput.readlines()[0].split(' ')
            
            new_result = float(output[0])
            results[test] += new_result
            iterations[test] += float(output[1])
            times[test] += elapsed
            
            foutput.close()
        
        global_results += [ list(results) ]
        global_iterations += [ list(iterations) ]
        global_times += [ list(times) ]
    
    f.write("\\\\\n\\hline\n")
    criteria(f, "Mejor", global_results, global_times, global_iterations,
             min, cases)
    criteria(f, "Prom", global_results, global_times, global_iterations,
             (lambda x : sum(x)/test_cases), cases)
    criteria(f, "Peor", global_results, global_times, global_iterations,
             max, cases)
    
    f.write("\\end{tabular}\n")
    f.close()
    
    return global_results, global_iterations, global_times

def global_tables(instances, heuristics, map_results, map_iteration, map_times,
                  outputfile):
    
    def mean(a):
        return sum(a)*1.0/len(a)
    
    for (inst, _) in instances:
        f= open(outputfile + "_global_table_" + inst + ".tex", "w")
       
        f.write("\\begin{tabular}{|c|c|c|c|c|c|}\n")
        f.write("\\hline\n")
        f.write("\\multicolumn{6}{|c|}{\\textbf{" + inst + "}}\\\\\n")
        f.write("\\hline\n")
        f.write(" & Peor & Mejor & Promedio & T$_{prom}(seg)$ & \#Iter$_{prom}$\\\\\n")
        f.write("\\hline\n")
        
        worst_val = min( [  max( map_results[ (inst,h) ]) for h in heuristics] )
        best_val  = min( [  min( map_results[ (inst,h) ]) for h in heuristics] )
        mean_val  = min( [ mean( map_results[ (inst,h) ]) for h in heuristics] )
        
        for h in heuristics:
            f.write(h)
            if max( map_results[ (inst,h)] ) == worst_val:
                f.write(" & \\textbf{" + str(round(float(max( map_results[ (inst,h)] )),4)) + "}")
            else:
                f.write(" & " + str(round(float(max( map_results[ (inst,h)] )),4)))
            
            if min( map_results[ (inst,h)] ) == best_val:
                f.write(" & \\textbf{" + str(round(float(min( map_results[ (inst,h)] )),4)) + "}")
            else:
                f.write(" & " + str(round(float(min( map_results[ (inst,h)] )),4)))
            
            if mean( map_results[ (inst,h)] ) == mean_val:
                f.write(" & \\textbf{" + str(round(float(mean( map_results[ (inst,h)] )),4)) + "}")
            else:
                f.write(" & " + str(round(float(mean( map_results[ (inst,h)] )),4)))
                
            f.write(" & " + str(round(float(mean( map_times[ (inst,h)] )),4)))
            f.write(" & " + str(round(float(mean( map_iteration[ (inst,h)] )),4)))
            f.write("\\\\\n")
            f.write("\\hline\n")
        f.write("\\end{tabular}\n")
        f.close()

def run_metaheuristic(num_experiments, inputfile, outputfile):
    
    f = open(inputfile)
    lines = f.readlines()
    
    num_heuristics = int(lines[0])
    
    heuristics = []
    iterations = []
    for i in range(num_heuristics):
        l = lines[1+i].split(' ')
        heuristics += [ l[0] ]
        iterations += [ int(l[1]) ]
    
    map_results   = {}
    map_times     = {}
    map_iteration = {}
    
    print
    print "Num Heuristics:", num_heuristics
    print "Heuristics:"
    print '\n'.join(
        [ "    ("+x+","+str(y)+")" for (x,y) in zip(heuristics, iterations) ])
    
    l = 1 + num_heuristics
    
    instances = []
    
    print
    print "Instances:"
    
    while int(lines[l]) != 0:
        
        num = int(lines[l])
        l += 1
        current = []
        for i in range(num):
            current += [ (lambda x : (x[0], int(x[1])))(lines[l].split(' ')) ]
            
            (x,_) = current[ len(current) - 1]
            print " ", x,
            
            l +=1
        instances += [ current ]
    
    print '\n'
    
    f.close()
    
    for (h,i) in zip(heuristics, iterations):
        
        for index in range(len(instances)):
            results, iteration, times = evaluate( instances[index], h, i,
                                           outputfile + h + str(index) + ".tex",
                                           num_experiments
                                           )
            
            # Informacion para tablas globales
            for k in range(len(instances[index])):
                (inst, _) = instances[index][k]
                
                map_results[(inst,h)] = results[k]
                map_iteration[(inst,h)] = iteration[k]
                map_times[(inst,h)] = times[k]
    
    print "Fin de calculos"
    
    instances = reduce( lambda x,y : x+y, instances )
    global_tables(instances, heuristics, map_results, map_iteration, map_times,
                  outputfile)
    os.system("rm salida.tmp")
    
if __name__ == "__main__":
    run_metaheuristic(int(sys.argv[1]), sys.argv[2], sys.argv[3])
